package device

import (
	"gorm.io/gorm"
	"iot/common"
	"iot/common/sys"
	"sync"
)

var (
	deviceMgrInstance *CDeviceMgr
	deviceMgrOnce     sync.Once
)

type CDeviceMgr struct {
	devs      map[string]*CDevice // 设备索引到设备对象的映射
	devArgIdx map[string]*CDevice
	groupIdx  map[string]*CDevice
	db        *gorm.DB
	mu        sync.RWMutex // 保护并发访问
}

// GetDeviceMgr 获取设备管理器单例
func GetDeviceMgr() *CDeviceMgr {
	deviceMgrOnce.Do(func() {
		deviceMgrInstance = &CDeviceMgr{
			devs:      make(map[string]*CDevice),
			devArgIdx: make(map[string]*CDevice),
			groupIdx:  make(map[string]*CDevice),
			db:        sys.DbIns(),
		}
	})
	return deviceMgrInstance
}

// Init 从数据库加载所有设备数据
func (mgr *CDeviceMgr) Init() error {
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	// 1. 加载所有设备
	var devices []common.SDeviceInfo
	if err := mgr.db.Find(&devices).Error; err != nil {
		return err
	}

	for _, devInfo := range devices {
		device := &CDevice{
			SDeviceInfo:   devInfo,
			ArgumentMap:   make(map[string]*CArgument),
			ArgumentGroup: make(map[string][]*CArgument),
			PermissionMap: make(map[string]common.EPermissionLevel),
			InstrucQueue:  make(chan *SInstruction, 200),
			ArgumentList:  []CArgument{},
		}
		mgr.devs[devInfo.PIndex] = device

		// 2. 加载设备的分组
		var groups []common.SGroupInfo
		if err := mgr.db.Where("device_index = ?", devInfo.PIndex).Find(&groups).Error; err != nil {
			return err
		}

		for _, group := range groups {
			// 3. 加载分组下的参数
			var args []common.SArgumentInfo
			if err := mgr.db.Where("group_index = ?", group.PIndex).Find(&args).Error; err != nil {
				return err
			}

			for _, argInfo := range args {
				arg := CArgument{
					SArgumentInfo: argInfo,
					SRtValue:      SRtValue{
						// 初始化实时值
					},
				}

				// 4. 加载参数的跟随关系
				var follows []common.FollowArg
				if err := mgr.db.Where("push_index = ?", argInfo.PIndex).Find(&follows).Error; err == nil {
					for _, follow := range follows {
						arg.FollorIdxs = append(arg.FollorIdxs, follow.FollowIndex)
					}
				}

				// 将参数添加到设备
				device.ArgumentList = append(device.ArgumentList, arg)
				currentArg := &device.ArgumentList[len(device.ArgumentList)-1]
				device.ArgumentMap[argInfo.PIndex] = currentArg
				device.ArgumentGroup[group.PIndex] = append(device.ArgumentGroup[group.PIndex], currentArg)
				mgr.devArgIdx[argInfo.PIndex] = device
			}
			mgr.groupIdx[group.PIndex] = device
		}

		// 5. 加载设备权限
		var perms []common.SDevicePermission
		if err := mgr.db.Where("device_index = ?", devInfo.PIndex).Find(&perms).Error; err == nil {
			for _, perm := range perms {
				device.PermissionMap[perm.UserIndex] = perm.Permission
			}
		}
	}

	return nil
}

// GetDevice 获取设备对象
func (mgr *CDeviceMgr) Device(devIdx string) *CDevice {
	mgr.mu.RLock()
	defer mgr.mu.RUnlock()
	return mgr.devs[devIdx]
}

func (mgr *CDeviceMgr) DeviceByArgIndex(idx string) *CDevice {
	dev, ex := mgr.devArgIdx[idx]
	if !ex {
		return nil
	}
	return dev
}

func (mgr *CDeviceMgr) DeviceByGroupIndex(idx string) *CDevice {
	dev, ex := mgr.groupIdx[idx]
	if !ex {
		return nil
	}
	return dev
}
